package javaLab.customClassLoader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class CustomClassLoader extends ClassLoader{
	private byte[] getBytes(String fileName) throws IOException{
		 File file = new File( fileName );
		 long len = file.length();
		 byte raw[] = new byte[(int)len];
		 FileInputStream fin = new FileInputStream( file );
		 int r = fin.read( raw );
		 if (r != len)
			 throw new IOException( "Can't read all, "+r+" != "+len );
		 fin.close();
		 return raw;
	}
	
	private boolean compile(String javaFile) throws IOException{
		System.out.println( "CCL: Compiling "+javaFile+"..." );
		Process p = Runtime.getRuntime().exec( "javac -d ./target/classes " + javaFile);
		try {
			p.waitFor();
		} catch( InterruptedException ie ) { System.out.println( ie );}
		int ret = p.exitValue();
		return ret==0;
	}
	
	@Override
	public Class loadClass(String name, boolean resolve)
	throws ClassNotFoundException{
		Class result = null;
		result = findLoadedClass(name);
		String filePath = name.replace('.', '/');
		String javaFileName = "src/main/java/"+filePath + ".java";
		String classFileName = "target/classes/"+filePath + ".class";
		File javaFile = new File(javaFileName);
		File classFile = new File(classFileName);

		if (javaFile.exists() &&
				 (!classFile.exists() ||
				 javaFile.lastModified() > classFile.lastModified())) {
			try{
				if (!compile( javaFileName ) || !classFile.exists()) {
					 throw new ClassNotFoundException( "Compile failed: "+javaFileName );
				}
			} catch (IOException ie){
				throw new ClassNotFoundException(ie.toString());
			}
		}
		try{
			byte[] raw = getBytes(classFileName);
			result = defineClass(name, raw, 0, raw.length);
		} catch (IOException ie){
			if(result == null)
				result = findSystemClass(name);
		}
	
		if(resolve && result != null)
			resolveClass(result);
		
		if(result == null)
			throw new ClassNotFoundException(name);

		return result;
	}
	
	
}
